package com.example.aigc_education.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.aigc_education.common.BusinessException;
import com.example.aigc_education.domain.Exam;
import com.example.aigc_education.domain.dto.UpdateExamByAdminDTO;
import com.example.aigc_education.domain.po.SelectExamByCourseIdPO;
import com.example.aigc_education.mapper.ExamMapper;
import com.example.aigc_education.service.ExamService;
import com.example.aigc_education.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService {
    @Resource
    private ExamMapper examMapper;


    /**
     * 根据用户ID查询所有考试信息
     *
     * @param userId 用户的唯一标识ID。
     * @return 包含所选用户参与的考试名称的列表。
     */
    @Override
    public List<Exam> selectExamByUserId(Long userId){
        // 创建查询条件对象
        QueryWrapper<Exam> wrapper = new QueryWrapper<>();
        // 设置查询条件：用户ID等于传入的userId
        wrapper.eq("user_id", userId);
        // 调用examMapper的selectList方法，根据查询条件获取考试列表
        List<Exam> exams = examMapper.selectList(wrapper);
        // 返回查询结果
        return exams;
    }

    /**
     * 根据用户ID和考试状态查询考试信息。
     *
     * @param userId 用户ID，用于查询该用户下的考试信息。
     * @param status 考试状态，用于筛选特定状态的考试。
     * @return 返回符合条件的考试列表。
     */
    @Override
    public List<Exam> selectExamByUserIdAndStatus(Long userId, Integer status){
        // 创建查询条件对象
        QueryWrapper<Exam> wrapper = new QueryWrapper<>();
        // 设置查询条件：用户ID等于传入的userId
        wrapper.eq("user_id", userId);
        // 设置查询条件：考试状态等于传入的status
        wrapper.eq("status", status);
        // 调用examMapper的selectList方法，根据查询条件获取考试列表
        List<Exam> exams = examMapper.selectList(wrapper);
        // 返回查询结果
        return exams;
}

    /**
     * 根据用户ID查询用户的考试成绩信息
     *
     * @param userId 用户的唯一标识ID。
     * @return 返回该用户所有已完成考试的成绩列表。
     */
    @Override
    public List<Exam> selectGrades(Long userId) {
        // 创建查询条件对象
        QueryWrapper<Exam> wrapper = new QueryWrapper<>();
        // 设置查询条件：用户ID等于指定的userId
        wrapper.eq("user_id", userId);
        // 设置查询条件：考试状态等于1,只有已完成的考试才有成绩
        wrapper.eq("status", 1);
        // 根据查询条件，从数据库中查询符合条件的考试成绩列表
        List<Exam> exams = examMapper.selectList(wrapper);
        // 返回查询结果
        return exams;
    }



    /**
     * 根据用户ID和考试类型查询考试成绩
     *
     * 本方法通过查询条件构造器QueryWrapper，构建查询条件，然后调用examMapper的selectList方法，
     * 根据这些条件查询Exam表中对应用户ID、考试类型且状态为1（表示有效的）的考试记录。
     *
     * @param userId 用户ID，用于筛选属于特定用户的考试记录。
     * @param examType 考试类型，用于筛选特定类型的考试记录。
     * @return 返回符合条件的考试记录列表。
     */
    @Override
    public List<Exam> selectGradesByExamType(Long userId, Integer examType){
        // 创建查询条件对象
        QueryWrapper<Exam> wrapper = new QueryWrapper<>();
        // 设置查询条件：用户ID
        wrapper.eq("user_id", userId);
        // 设置查询条件：考试类型
        wrapper.eq("exam_type", examType);
        // 设置查询条件：考试状态为已完成（1）
        wrapper.eq("status", 1);
        // 根据查询条件查询考试记录列表
        List<Exam> exams = examMapper.selectList(wrapper);
        // 返回查询结果
        return exams;
    }

    /**
     * 根据课程ID查询相应的考试信息。
     *
     * 本方法通过调用examMapper的selectExamByCourseId方法，根据指定的课程ID查询相关的考试信息。
     * 这里的考试信息是通过SelectExamByCourseIdPO对象来表示的，该对象包含了与考试相关的详细数据。
     *
     * @param courseId 课程的唯一标识ID，用于指定查询的课程。
     * @return 返回一个List集合，其中包含了所有与指定课程ID相关的考试信息。
     */
//    @Override
//    public List<SelectExamByCourseIdPO> selectExamByCourseId(Long courseId){
//        // 调用examMapper的selectExamByCourseId方法，查询指定课程ID的考试信息
//        return examMapper.selectExamByCourseId(courseId);
//    }
//
//    @Override
//    public List<SelectExamByCourseIdPO> selectExamByCourseIdAndUserId(Long courseId, Long userId){
//        // 调用examMapper的selectExamByCourseIdAndUserId方法，查询指定课程ID和用户ID的考试信息
//        return examMapper.selectExamByCourseIdAndUserId(courseId, userId);
//    }

    /**
     * 根据课程ID和用户ID查询相应的考试信息
     * 如果用户ID为null，则只根据课程ID查询考试信息。
     * 这种方法的设计允许通过一个方法来处理两种查询场景：一种是只根据课程ID查询，另一种是同时根据课程ID和用户ID查询。
     * 这样做可以简化接口的使用和维护。
     *
     * @param courseId 课程的唯一标识ID，用于指定查询的课程。
     * @param userId 用户的唯一标识ID，用于过滤查询的考试信息（可选）。
     * @return 返回一个List集合，其中包含了所有与指定课程ID和（可选的）用户ID相关的考试信息。
     */
    @Override
    public List<SelectExamByCourseIdPO> selectExamByCourseIdAndUserId(Long courseId, Long userId){
        // 根据用户ID是否为空来决定查询的策略
        if (userId == null){
            // 如果用户ID为空，则只根据课程ID查询考试信息
            return examMapper.selectExamByCourseId(courseId);
        }else {
            // 如果用户ID不为空，则同时根据课程ID和用户ID查询考试信息
            return examMapper.selectExamByCourseIdAndUserId(courseId, userId);
        }
    }

    /**
     * 根据班级ID查询相应的考试信息
     *
     * 本方法通过调用examMapper的selectExamByClassId方法，根据指定的班级ID检索与该班级相关的考试信息。
     * 这对于需要对特定班级的考试成绩进行统计或管理的场景非常有用。
     *
     * @param classId 班级的唯一标识ID。这个参数用于精确地定位到某个班级，以便查询该班级下的考试信息。
     * @return 返回一个包含考试信息的列表。每个元素都是SelectExamByCourseIdPO类型的对象，代表了一次考试的详细信息。
     */
    @Override
    public List<SelectExamByCourseIdPO> selectExamByClassId(Long classId){
        // 调用examMapper的selectExamByClassId方法，查询指定班级ID下的所有考试信息
        return examMapper.selectExamByClassId(classId);
    }

    /**
     * 查询所有考试信息
     *
     * 本方法通过调用examMapper的selectAllExam方法，获取数据库中所有考试的信息。
     * 这对于需要列出所有考试或进行考试信息统计的场景非常有用。
     *
     * @return List<SelectExamByCourseIdPO> 返回一个包含所有考试信息的列表。
     */
    @Override
    public List<SelectExamByCourseIdPO> selectAllExam(){
        // 调用examMapper的selectAllExam方法，查询所有考试信息
        return examMapper.selectAllExam();
    }


    /**
     * 根据考试ID更新考试信息。
     * 通过UpdateExamByAdminDTO对象中的非空属性来更新对应考试的信息。
     * 这种方法适用于批量更新考试的多个属性，而不需要单独的方法来更新每个属性。
     *
     * @param updateExamByAdminDTO 包含待更新考试信息的数据传输对象。
     * @param examId 需要更新的考试的ID。
     */
    @Override
    @Transactional
    public void updateExamByExamId(UpdateExamByAdminDTO updateExamByAdminDTO, Long examId){
        UpdateWrapper<Exam> wrapper = new UpdateWrapper<>();
        // 根据updateExamByAdminDTO中的非空属性，动态设置更新条件
        if (updateExamByAdminDTO.getCorrectAnswerNum() != null){
            wrapper.set("correct_answer_num", updateExamByAdminDTO.getCorrectAnswerNum());
        } else if (updateExamByAdminDTO.getExamId() != null) {
            wrapper.set("exam_id", updateExamByAdminDTO.getExamId());
        } else if (updateExamByAdminDTO.getCreateBy() != null){
            wrapper.set("create_by", updateExamByAdminDTO.getCreateBy());
        } else if (updateExamByAdminDTO.getCreateTime() != null){
            wrapper.set("create_time", updateExamByAdminDTO.getCreateTime());
        } else if (updateExamByAdminDTO.getExamName() != null){
            wrapper.set("exam_name", updateExamByAdminDTO.getExamName());
        } else if (updateExamByAdminDTO.getExamType() != null){
            wrapper.set("exam_type", updateExamByAdminDTO.getExamType());
        } else if (updateExamByAdminDTO.getUserId() != null){
            wrapper.set("user_id", updateExamByAdminDTO.getUserId());
        } else if (updateExamByAdminDTO.getExamStartTime() != null){
            wrapper.set("exam_start_time", updateExamByAdminDTO.getExamStartTime());
        } else if (updateExamByAdminDTO.getExamEndTime() != null){
            wrapper.set("exam_end_time", updateExamByAdminDTO.getExamEndTime());
        } else if (updateExamByAdminDTO.getExamTime() != null){
            wrapper.set("exam_time", updateExamByAdminDTO.getExamTime());
        } else if (updateExamByAdminDTO.getScore() != null){
            wrapper.set("score", updateExamByAdminDTO.getScore());
        } else if (updateExamByAdminDTO.getStatus() != null){
            wrapper.set("status", updateExamByAdminDTO.getStatus());
        } else if (updateExamByAdminDTO.getPaperId() != null){
            wrapper.set("paper_id", updateExamByAdminDTO.getPaperId());
        } else if (updateExamByAdminDTO.getCourseId() != null){
            wrapper.set("course_id", updateExamByAdminDTO.getCourseId());
        }

        if (updateExamByAdminDTO.getUpdateBy() != null){
            wrapper.set("update_by", updateExamByAdminDTO.getUpdateBy());
        } else {
            wrapper.set("update_by", SecurityUtils.getUserId());
        }

        if (updateExamByAdminDTO.getUpdateTime() != null){
            wrapper.set("update_time", updateExamByAdminDTO.getUpdateTime());
        } else {
            wrapper.set("update_time", LocalDateTime.now());
        }
        // 指定更新的考试ID
        wrapper.eq("exam_id", examId);
        examMapper.update(null, wrapper);

    }


    /**
     * 根据考试ID删除考试信息
     *
     * 本方法通过调用examMapper的DeleteById方法，传入考试ID，来实现对特定考试记录的删除。
     * 这里的考试ID是作为主键标识考试记录的唯一标识符。
     *
     * @param examId 需要删除的考试的唯一标识符。
     */
    @Override
    @Transactional
    public void deleteExamByExamId(Long examId){
        examMapper.deleteById(examId);
    }

    /**
     * 添加考试信息。
     *
     * 本方法通过使用事务确保操作的完整性。在方法执行过程中，如果出现任何异常，
     * 事务将会回滚以防止数据不一致的情况发生。
     *
     * @param exam 要添加的考试对象，包含考试的所有相关信息。
     * @throws BusinessException 如果考试添加过程中出现任何异常，将会抛出运行时异常。
     */
    @Override
    @Transactional
    public void addExam(Exam exam) {
       try {
           // 设置考试创建者信息，通过SecurityUtils获取当前用户的ID。
        exam.setCreateBy(SecurityUtils.getUserId());
        // 设置考试的创建时间，使用当前时间。
        exam.setCreateTime(LocalDateTime.now());
        // 将考试信息插入到数据库中。
        examMapper.insert(exam);
       }catch (Exception e){
           // 如果插入过程中出现异常，抛出运行时异常。
           throw new BusinessException("添加考试失败");
       }
}


    /**
     * 修改考试成绩。
     * 该方法用于根据考试ID更新相应的考试成绩。通过构建更新条件包装器，指定需要更新的分数和对应的考试ID，
     * 然后调用考试Mapper的更新方法来执行数据库操作。
     *
     * @param examId 考试ID，用于指定需要更新成绩的考试。
     * @param score 新的考试成绩，用于更新数据库中相应考试的成绩。
     */
    @Override
    @Transactional
    public void updateScore(Long examId, Integer score){
        try {
        // 创建UpdateWrapper实例，用于构建更新条件。
        UpdateWrapper<Exam> wrapper = new UpdateWrapper<>();
        // 设置需要更新的字段及其值，此处为考试成绩。
        wrapper.set("score", score);
        // 设置更新条件，此处为考试ID等于传入的examId。
        wrapper.eq("exam_id", examId);
        // 调用考试Mapper的update方法，传入null表示更新整个实体，wrapper作为更新条件。
        examMapper.update(null, wrapper);
    }catch (Exception e){
        // 如果更新过程中出现异常，抛出运行时异常。
        throw new BusinessException("更新考试成绩失败");
    }















}}
